#ifndef IGSLIB_ISERIAL_MANAGER_H
#define IGSLIB_ISERIAL_MANAGER_H

#include <string>
#include <map>
#include "igslib_common_use.h"

namespace igslib
{
	struct ISpi;
	struct IUart;

	struct ISerialEvent
    {
        /**
         * 當收到資料時觸發。
         * @param a0 收到的byte值。
         */
        virtual void OnRxData(char)=0;
        /**
         * 當收完資料時觸發。
         * @param a0 所有收到的byte資料。
         * @param a1 byte數。
         */
        virtual void OnRxData(char*,int)=0;
	     /**
         * 當收完資料時觸發。
		 * @param a0 要取回資料的傳輸器。
         * @param a1 所有收到的byte資料。
         * @param a2 byte數。
         */
		//virtual void OnRxData(ISpi*,char*,int)=0;
		/**
         * 當收完資料時觸發。
		 * @param a0 要取回資料的傳輸器。
         * @param a1 所有收到的byte資料。
         * @param a2 byte數。
         */
		//virtual void OnRxData(IUart*,char*,int)=0;
    };

	struct ISerial:public IComponent
	{
        /**
         * 設定事件觸發時的處理者。
         * @param a0 事件觸發時的處理者。
         */
        virtual void SetEventHandler(ISerialEvent*)=0;
        /*!
         * 傳送資料。
         * @param a0 序列化後的資料起始位址。
         * @param a1 要傳送的資料長度。
         * @return 實際傳送出去的資料長度。
         */
		virtual int Send(char*,int)=0;
        /*!
         * 傳送上次Send()的資料。
         * @return 實際傳送出去的資料長度。
         */
		virtual int ReSend()=0;
        /*!
         * 接收資料。
         * @param [out] a0 序列化後的資料起始位址。
         * @param a1 要接收的資料長度。
         * @return 實際接收到的資料長度。
         */
		virtual int Receive(char*,int)=0;
        /*!
         * 設定裝置名稱。
         * @param a0 裝置名稱。
         */
        virtual void SetName(std::string)=0;
        /*!
         * 取得裝置名稱。
         * @return 裝置名稱。
         */
        virtual std::string GetName()=0;
        //! 關閉裝置。
        virtual void Close()=0;
        //! 清空裝置自己的緩衝區。
        virtual void FlushBuffer()=0;
        /// 更新裝置狀態。
        virtual int Update()=0;
        virtual ~ISerial() { }
	};

    struct ISpi:virtual public ISerial
    {
        enum ChipSelector
        {
            cs0,
            mcu = cs0,
            cs1,
            fram = cs1,
            cs2,
            cs3,
            cs4,
        };
        /*!
         * 全雙工傳送接收。
         * @param [out] a0 欲傳送的資料緩存區。
		 * @param a1 接收到的資料緩存區。
		 * @param a2 接收資料緩存區長度。
         * @return true代表操作都成功，false代表其中有一個操作是失敗的。
         */
        virtual bool FullDuplexReadWrite(char*,char*,int) = 0;
		 /*!
         * 半雙工傳送接收。
         * @param [out] a0 欲傳送的資料緩存區。
		 * @param a1 傳送資料緩存區長度。
		 * @param a2 接收到的資料緩存區。
		 * @param a3 接收資料緩存區長度。
         * @return true代表傳送/接受操作都成功，false代表其中有一個操作是失敗的。
         */
        virtual bool HalfDuplexReadWrite(char*,int,char*,int) = 0;	
        /*!
         * 開啟可存取裝置。
         * @param a0 可存取裝置。
         * @return true代表成功。
         */
        virtual bool Open(ChipSelector) = 0;
        /*!
         * 設定裝置工作頻率。
         * @param a0 工作頻率值，單位為Hz。
         */
        virtual void SetWorkingFrequency(int) = 0;
        /*!
         * 取得裝置工作頻率。
         * @return 工作頻率值，單位為Hz。
         */
        virtual int GetWorkingFrequency() = 0;

    };
    struct IUart:virtual public ISerial
    {
        enum DeviceNumber
        {
            ttyS0,
            COM1 = ttyS0,
            ttyS1,
            COM2 = ttyS1,
            ttyS2,
            COM3 = ttyS2,
            ttyS3,
            COM4 = ttyS3,
            ttyS4,
            COM5 = ttyS4,
            ttyS5,
            COM6 = ttyS5,
            ttyS6,
            COM7 = ttyS6,
            ttyS7,
            COM8 = ttyS7,
            ttyS8,
            COM9 = ttyS8,
            ttyS9,
            COM10 = ttyS9,
            ttyS10,
            COM11 = ttyS10,
            ttyS11,
            COM12 = ttyS11,
            ttyS12,
            COM13 = ttyS12,
            ttyS13,
            COM14 = ttyS13,
            ttyS14,
            COM15 = ttyS14,
            ttyS15,
            COM16 = ttyS15,
            ttyUSB0,
            ttyUSB1,
            ttyUSB2,
            ttyUSB3,
            ttyUSB4,
            ttyUSB5,
            ttyAMA0,
            ttyAMA1,
            ttyACM0,
            ttyACM1,
            rfcomm0,
            rfcomm1,
            ircomm0,
            ircomm1,
            ttyXRUSB0, //!< At 'con2' lower port on MI board.
            ttyXRUSB1, //!< At 'con2' upper port on MI board.
            ttyXRUSB2, //!< At 'con3' lower port on MI board.
            ttyXRUSB3, //!< At 'con3' upper port on MI board.
            Auto,
        };
		enum BAUDRATE
        {
		   BAUDRATE_300 = 300 , 
		   BAUDRATE_1200 = 1200 , 
		   BAUDRATE_2400 = 2400 , 
		   BAUDRATE_4800 = 4800 , 
		   BAUDRATE_9600 = 9600 , 
		   BAUDRATE_19200 = 19200 ,
		   BAUDRATE_38400 = 38400 ,
		   BAUDRATE_57600 = 57600 ,
		   BAUDRATE_115200 = 115200 ,
		};
        enum ParityMode
        {
            pm_none,
            pm_odd,
            pm_even,
        };
        enum DataBits
        {
            data_5bits,
            data_6bits,
            data_7bits,
            data_8bits,
            data_9bits,
        };
        enum StopBits
        {
            stop_1bit,
            stop_2bits,
        };
        /*!
         * 設定鮑率速度。
         * @param a0 鮑率速度。單位為bits/second。
         */
        virtual void SetBaudRate(int)=0;
        /*!
         * 取得目前設定的鮑率速度。
         * @return 鮑率速度。單位為bits/second。
         */
        virtual int GetBaudRate()=0;
        /*!
         * 設定同位元檢查模式。
         * @param a0 同位元檢查模式。
         */
        virtual void SetParityMode(ParityMode)=0;
        /*!
         * 取得同位元檢查模式。
         * @return 同位元檢查模式。
         */
        virtual ParityMode GetParityMode()=0;
        /*!
         * 設定封包資料位元數。
         * @param a0 封包資料位元數。
         */
        virtual void SetDataBits(DataBits)=0;
        /*!
         * 取得封包資料位元數。
         * @return 封包資料位元數。
         */
        virtual DataBits GetDataBits()=0;
        /*!
         * 設定終止資料位元數。
         * @param a0 終止資料位元數。
         */
        virtual void SetStopBits(StopBits)=0;
        /*!
         * 取得終止資料位元數。
         * @return 終止資料位元數。
         */
        virtual StopBits GetStopBits()=0;
        /*!
         * 開啟裝置的通訊埠。
         * @param a0 通訊埠編號。
         * @return 開啟結果，true表示成功。
         */
        virtual bool Open(DeviceNumber)=0;
	
		
    };
    struct IUart9bit:virtual public IUart
    {   
        /*!
         * 傳送資料。
         * @param a0 序列化後的資料起始位址。
         * @param a1 要傳送的資料長度。
         * @return 實際傳送出去的資料長度。
         */
        virtual int Send(short*,int)=0;
        /*!
         * 接收資料。
         * @param [out] a0 序列化後的資料起始位址。
         * @param a1 要接收的資料長度。
         * @return 實際接收到的資料長度。
         */
        virtual int Receive(short*,int)=0;
    };	
	struct IMCUUart:virtual public IUart
	{
		enum class UState
        {
            DValid, //!< Data valid
            Transferring ,//!<傳送中
            DInvalid, //!< Data invalid
            Error, //!<MCU端 uart error
        };
		 
		enum class WorkMode
        {
            passing,
            function,
        };
		/*!
		 * 設定MCU的RS232/RS485的工作模式
		 *@param a0 工作模式
		 */
		virtual void SetWorkMode(WorkMode) = 0 ;
		
		/*!
         * 設定MCU端USART對外接收資料的長度
         * @param a0 接收長度。
         */
		virtual void SetReceiveLen(int) = 0 ;
		/*!
         * 設定MCU端USART對外接收資料封包timeout時間
         * @param a0 timeout時間 unit: ms。
         */
		virtual void SetReceiveTimeout(int) = 0 ;	
		/*!
         * 取得MCU端USART工作狀態
         * @return UState
         */
		virtual UState GetState() = 0 ;	
		/*!
         * 設定MCU端USART對外為Slave裝置
         * @param a0 true表示是slave。
         */
		virtual void SetSlaveOperation(bool) = 0 ;
		
		/*!
         * 若實作是使用SPI通訊介面，用此函式輸入SPI的實作。
         * @param a0 SPI的實作。
         */
		virtual void SetSPI(ISpi*) = 0 ;
	};
	
    struct ICanbus:virtual public ISerial
    {
        /*!
         * 設定本機ID。
         * @param a0 本機ID值。
         */
        virtual void SetID(const int&) = 0;
        /*!
         * 取得本機ID。
         * @return 本機ID值。
         */
        virtual int GetID() = 0;
        /*!
         * 設定目的端ID。
         * @param a0 目的端ID值。
         */
        virtual void SetTargetID(const int&) = 0;
        /*!
         * 取得目的端ID。
         * @return 目的端ID值。
         */
        virtual int GetTargetID() = 0;
		/*!
         * 若實作是使用SPI通訊介面，用此函式輸入SPI的實作。
         * @param a0 SPI的實作。
         */
		 virtual void SetSPI(ISpi*) =0 ;
    };

	struct ISerialManager:public IManager<ISerial*>
	{
		/*!
         * 創建一個非同步序列傳輸器。
         * @return 非同步序列傳輸器。
         */
		virtual IUart* NewM01Uart()=0;
        /*!
         * 創建一個SPI通訊協定之序列傳輸器。
         * @return SPI通訊協定之序列傳輸器。
         */
		virtual ISpi* NewM01Spi()=0;
		/*!
         * 創建MH主板上根據專案特規實作MCU SPI資源。
         * @param a0 專案名。
         * @return MCU端 ISpi 介面
         * @note
         *     目前已實作專案名對照如下：
         *     "DragonBallRace"：龍珠賽球
         *     "DragonWarrior"：鬥龍戰士
         */
		virtual ISpi* New_ProjMCU_spi(const std::string&)=0;
        /*!
         * 創建一個Canbus通訊協定之序列傳輸器。
         * @return Canbus通訊協定之序列傳輸器。
         */
		virtual ICanbus* NewM01Canbus()=0;
		/*!
         * 創建MH主板上根據專案特規實作MCU CanBus資源。
         * @param a0 專案名。
         * @return MCU端 ICanbus 介面
         * @note
         *     目前已實作專案名對照如下：
         *     "DragonBallRace"：龍珠賽球
         */
        virtual ICanbus* New_ProjMCU_canbus(const std::string&)=0;
        /*!
         * 創建一個9bit非同步序列傳輸器。
         * @return 9bit非同步序列傳輸器。
         */
        virtual IUart9bit* NewM01Uart9bit()=0;

		/*!
         * 創建MH主板上根據專案特規實作MCU UART資源。
         * @param a0 專案名。
         * @return MCU端 IMCUUart 介面
         * @note
         *     目前已實作專案名對照如下：
         *     "DragonBallRace"：龍珠賽球
         */
		 
        virtual std::map<std::string,IMCUUart*> New_ProjMCU_uart(const std::string&)=0;	
		
	};
}
extern "C"{
    igslib::ISerialManager* GetSerialManagerInstance();
};

#endif

